package com.justnow.offer.q1;

/**
 * 这个方法适合进行无限次打印输出内容
 * https://www.cnblogs.com/ynyhl/articles/11850958.html
 */
public class SynchronizedDemo01 {

    private int flag = 0;

    public synchronized void printa() throws InterruptedException {

        while (true) {
            if (flag == 0) {
                System.out.println("A");
                flag = 1;
                notifyAll();//使其他线程有等待状态进入阻塞队列中，等待拿到对象的锁
            }
            wait();//执行该方法的线程释放锁，并且进入等待状态
        }
    }

    public synchronized void printb() throws InterruptedException {

        while (true) {
            if (flag == 1) {
                System.out.println("B");
                flag = 2;
                notifyAll();//是其他线程有等待状态进入阻塞队列中，等待拿到对象的锁
            }
            wait();//执行该方法的线程释放锁，并且进入等待状态
        }

    }

    public synchronized void printc() throws InterruptedException {

        while (true) {
            if (flag == 2) {
                System.out.println("C");
                flag = 0;
                notifyAll();//是其他线程有等待状态进入阻塞队列中，等待拿到对象的锁
            }
            wait();//执行该方法的线程释放锁，并且进入等待状态
        }
    }

    public static void main(String[] args) {
        SynchronizedDemo01 t = new SynchronizedDemo01();
        PrintA printA = new PrintA(t);
        PrintB printB = new PrintB(t);
        PrintC printC = new PrintC(t);
        Thread threadA = new Thread(printA);
        Thread threadB = new Thread(printB);
        Thread threadC = new Thread(printC);
        threadA.start();
        threadB.start();
        threadC.start();

    }
}

class PrintA implements Runnable {

    private SynchronizedDemo01 t;

    public PrintA(SynchronizedDemo01 t) {
        this.t = t;
    }

    @Override
    public void run() {
        try {
            t.printa();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class PrintB implements Runnable {

    private SynchronizedDemo01 t;

    public PrintB(SynchronizedDemo01 t) {
        this.t = t;
    }

    @Override
    public void run() {
        try {
            t.printb();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class PrintC implements Runnable {

    private SynchronizedDemo01 t;

    public PrintC(SynchronizedDemo01 t) {
        this.t = t;
    }

    @Override
    public void run() {
        try {
            t.printc();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
